<template>
	<div class="ai-component">
		<div class="ai-header">
			<div class="ai-title">
				<i class="iconfont icon-ai"></i>
				<span>AI数据分析</span>
			</div>
		</div>

		<div class="ai-content">
			<div v-if="loading && !aiSuggestion" class="ai-loading">
				<el-skeleton :rows="5" animated />
			</div>

			<div v-else-if="aiSuggestion" class="ai-message">
				<div
					class="message-content"
					:class="{ 'is-typing': loading }"
					v-html="formatMessageContent(aiSuggestion)"
				></div>
			</div>

			<div v-else class="ai-empty-state">
				<i class="iconfont icon-ai-assistant"></i>
				<div>数据分析中，请稍候...</div>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'

// 定义props
const props = defineProps({
	// 数据源，用于发送给AI进行分析
	dataSource: {
		type: Object,
		default: () => ({})
	},
	// 分析场景/上下文
	contentType: {
		type: String,
		default: '命令'
	},
	// 用户类型
	userTypeId: {
		type: Number,
		default: 1
	},
	// 执行什么操作
	doAction: {
		type: String,
		default: ''
	}
})

// 响应式状态
const aiSuggestion = ref('')
const loading = ref(false)
const controller = ref<AbortController | null>(null)

// 刷新AI建议
const refreshAiSuggestion = () => {
	aiSuggestion.value = ''
	getAiSuggestion()
}

// 获取AI建议 - 流式响应版本
const getAiSuggestion = async () => {
	if (loading.value || !Object.keys(props.dataSource).length) return

	// 取消之前的请求
	if (controller.value) {
		controller.value.abort()
	}

	loading.value = true
	aiSuggestion.value = '' // 清空现有内容
	controller.value = new AbortController()

	try {
		// 准备发送给AI的数据
		const requestData = {
			data: props.dataSource,
			contentType: props.contentType,
			userTypeId: props.userTypeId,
			doAction: props.doAction || '提取score属性的值'
		}

		// 使用完整的后端URL并发送请求
		const response = await fetch('http://localhost:8899/api/ai/process/stream', {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify(requestData),
			signal: controller.value.signal
		})

		if (response.status !== 200) {
			throw new Error(`HTTP 错误: ${response.status}`)
		}

		// 处理流式响应
		const reader = response.body?.getReader()
		if (!reader) throw new Error('无法获取响应流')

		const decoder = new TextDecoder()
		let buffer = ''
		let inThinkingMode = false
		let visibleContent = ''

		// 处理SSE数据
		while (true) {
			const { done, value } = await reader.read()
			if (done) break

			const chunk = decoder.decode(value, { stream: true })
			buffer += chunk

			// 处理think标签
			// 检查是否有开始的思考标签
			const thinkStartIndex = buffer.indexOf('<think>')
			if (thinkStartIndex !== -1 && !inThinkingMode) {
				// 提取思考前的内容
				visibleContent += buffer.substring(0, thinkStartIndex)
				buffer = buffer.substring(thinkStartIndex)
				inThinkingMode = true
			}

			// 检查是否有结束的思考标签
			const thinkEndIndex = buffer.indexOf('</think>')
			if (thinkEndIndex !== -1 && inThinkingMode) {
				// 丢弃思考内容，保留思考后的内容
				buffer = buffer.substring(thinkEndIndex + 8) // 8 是 '</think>' 的长度
				inThinkingMode = false
			}

			// 如果不在思考模式，添加内容到可见文本
			if (!inThinkingMode) {
				visibleContent += buffer
				buffer = ''
			}

			// 更新UI
			aiSuggestion.value = visibleContent
		}
	} catch (error) {
		if (error.name !== 'AbortError') {
			console.error('AI分析请求错误:', error)
			ElMessage.error('分析数据时出错')
		}
	} finally {
		loading.value = false
		controller.value = null
	}
}

// 组件卸载前取消请求
onUnmounted(() => {
	if (controller.value) {
		controller.value.abort()
		controller.value = null
	}
})

// 当数据源变化时自动获取AI建议
watch(
	() => props.dataSource,
	(newVal) => {
		if (Object.keys(newVal).length) {
			aiSuggestion.value = ''
			getAiSuggestion()
		}
	},
	{ deep: true }
)

// 组件挂载时，如果有数据则自动获取AI建议
onMounted(() => {
	if (Object.keys(props.dataSource).length) {
		getAiSuggestion()
	}
})

// 格式化消息内容，处理代码块和其他格式
const formatMessageContent = (content) => {
	if (!content) return ''

	// 处理Markdown代码块
	let formatted = content.replace(
		/```(json|javascript|js|html|css|vue|typescript|ts)?\n([\s\S]*?)\n```/g,
		(match, lang, code) => {
			return `<pre class="language-${lang || 'text'}"><code>${escapeHtml(code)}</code></pre>`
		}
	)

	// 处理内联代码
	formatted = formatted.replace(/`([^`]+)`/g, '<code>$1</code>')

	return formatted
}

// HTML转义函数
const escapeHtml = (text) => {
	return text
		.replace(/&/g, '&amp;')
		.replace(/</g, '&lt;')
		.replace(/>/g, '&gt;')
		.replace(/"/g, '&quot;')
		.replace(/'/g, '&#039;')
}
</script>

<style scoped>
.ai-component {
	display: flex;
	flex-direction: column;
	width: 100%;
	height: 100%;
	border-radius: 8px;
	background-color: white;
	box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
	overflow: hidden;
}

.ai-header {
	padding: 12px 16px;
	background: linear-gradient(135deg, #3a8ee6, #13c2c2);
	color: white;
	display: flex;
	justify-content: space-between;
	align-items: center;
}

.ai-title {
	display: flex;
	align-items: center;
	font-weight: bold;
	font-size: 16px;
}

.ai-title i {
	margin-right: 8px;
	font-size: 20px;
}

.ai-content {
	flex: 1;
	padding: 16px;
	overflow-y: auto;
	background-color: #f9fafb;
	min-height: 200px;
}

.ai-message {
	margin-bottom: 12px;
}

.message-content {
	background-color: white;
	padding: 16px;
	border-radius: 8px;
	line-height: 1.6;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
	white-space: pre-wrap;
	font-family: var(--el-font-family);
	transition: background-color 0.3s;
	overflow-x: auto;
}

.message-content :deep(pre) {
	background-color: #f5f7fa;
	border-radius: 4px;
	padding: 12px;
	margin: 8px 0;
	font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
	overflow-x: auto;
}

.message-content :deep(code) {
	font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
	background-color: #f5f7fa;
	padding: 2px 4px;
	border-radius: 3px;
	font-size: 0.9em;
}

.ai-loading {
	padding: 12px;
	height: 100%;
}

.ai-empty-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	height: 180px;
	color: #909399;
}

.ai-empty-state i {
	font-size: 48px;
	margin-bottom: 16px;
	color: #3a8ee6;
}

.ai-actions {
	padding: 12px;
	display: flex;
	justify-content: flex-end;
	border-top: 1px solid #ebeef5;
}

/* 添加打字机光标效果 */
.is-typing::after {
	content: '|';
	animation: blink 0.8s infinite;
	margin-left: 2px;
	font-weight: bold;
}

/* 闪烁动画 */
@keyframes blink {
	0%,
	100% {
		opacity: 1;
	}
	50% {
		opacity: 0;
	}
}
</style>
